home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Mania 5
/
MacMania 5.toast
/
/
Internet software
/
NewsWatcher
/
NW Source
/
Source
/
sfutil.c
< prev
next >
Wrap
Text File
|
1997-01-09
|
17KB
|
529 lines
/*----------------------------------------------------------------------------
sfutil.c
This module contains Standard File utility routines.
Copyright © 1994-1997, Northwestern University.
----------------------------------------------------------------------------*/
#include <stdio.h>
#include "glob.h"
#include "sfutil.h"
#include "dialog.h"
#include "menus.h"
#include "newswatcher.h"
#include "strutil.h"
#include "fileutil.h"
#define kDirSelectDlg 200 /* Directory selection standard file dialog */
#define kSelectDirButtonTop 11
#define kSelectDirButtonBottom 10
#define kSaveArtDlg 201 /* Save article standard file dialog */
#define kSaveEncodedCheckbox 13
#define kSaveThreadsToSeparateFilesCheckbox 14
#define kAppendArtDlg 202 /* Append article standard file dialog */
#define kAppendEncodedCheckbox 10
static StandardFileReply *gReply; /* pointer to standard file reply record */
static Boolean *gSaveEncodedText; /* pointer to save encoded text option */
static Boolean *gSaveThreadsToSeparateFiles; /* pointer to save threads to separate
files option */
static AliasHandle gAlias; /* handle to alias to default directory,
or nil if none */
static FSSpec gDirTop; /* file selected in top button */
static FSSpec gDirBottom; /* file selected in bottom button */
static short gSelect; /* 0 = cancel, 1 = top select button, 2 = bottom select button */
static Str255 gPrevNameTop; /* previous name in top button */
static Str255 gPrevNameBottom; /* previous name in bottom button */
static DlgHookYDUPP gGetPutHookUPP = nil;
static DlgHookYDUPP gMyStandardAppendArticleHookUPP = nil;
static DlgHookYDUPP gMyStandardPutArticleHookUPP = nil;
static ModalFilterYDUPP gSFDialogFilterUPP = nil;
static FileFilterYDUPP gGetDirectoryFilterUPP = nil;
static DlgHookYDUPP gGetDirectoryHookUPP = nil;
/*----------------------------------------------------------------------------
SetStandardFileDirectoryFromAlias
Initialize the standard file directory from a saved folder alias.
Entry: gReply = pointer to standard file reply record, or nil if none.
gAlias = handle to alias.
Exit: function result = item number which should be returned to
standard file.
----------------------------------------------------------------------------*/
static short SetStandardFileDirectoryFromAlias (void)
{
short vRefNum, desktopVRefNum;
long dirID, desktopDirID;
Boolean valid;
OSErr err = noErr;
if (gAlias == nil) return sfHookFirstCall;
ValidateSavedFolderAlias(gAlias, &vRefNum, &dirID, &valid);
if (!valid) return sfHookFirstCall;
err = FindFolder(vRefNum, kDesktopFolderType, false,
&desktopVRefNum, &desktopDirID);
if (err == noErr && vRefNum == desktopVRefNum && dirID == desktopDirID) {
return sfHookGoToDesktop;
} else {
gReply->sfFile.vRefNum = vRefNum;
gReply->sfFile.parID = dirID;
*gReply->sfFile.name = 0;
return sfHookChangeSelection;
}
}
/*----------------------------------------------------------------------------
SFDialogFilter
Event filter for standard file dialogs.
----------------------------------------------------------------------------*/
static pascal Boolean SFDialogFilter (DialogPtr dlg, EventRecord *ev,
short *itemHit, void *yourDataPtr)
{
Boolean result = false;
OSErr err = noErr;
ModalFilterUPP standardFilterProcUPP;
if (ev->what == updateEvt && (WindowPtr)ev->message != dlg) {
HandleEvent(ev);
return false;
}
err = GetStdFilterProc(&standardFilterProcUPP);
if (err == noErr) {
result = CallModalFilterProc(standardFilterProcUPP, dlg, ev, itemHit);
}
return result;
}
/*----------------------------------------------------------------------------
GetPutHook
Dialog hook function for MyStandardGetFile and MyStandardPutFile.
----------------------------------------------------------------------------*/
static pascal short GetPutHook (short item, DialogPtr dlg, void *myDataPtr)
{
if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
if (item == sfHookFirstCall) {
return SetStandardFileDirectoryFromAlias();
} else {
return item;
}
}
/*----------------------------------------------------------------------------
MyStandardGetFile
Present the StandardGetFile dialog.
The parameters are the same as in StandardGetFile, plus:
Entry: alias = handle to alias to default directory, or nil if none.
----------------------------------------------------------------------------*/
void MyStandardGetFile (FileFilterYDUPP fileFilter, short numTypes,
char *typeListString, StandardFileReply *reply, AliasHandle alias)
{
Point where = {-1, -1};
SFTypeList typeList;
PrepUserInteraction();
SetMenusTo(kAppleAllEnabled, 0, 0, 0, 0, 0);
gReply = reply;
gAlias = alias;
BlockMoveData(typeListString, typeList, 4*numTypes);
CustomGetFile(fileFilter, numTypes, typeList, reply, 0, where, gGetPutHookUPP,
gSFDialogFilterUPP, nil, nil, nil);
}
/*----------------------------------------------------------------------------
MyStandardPutFile
Present the StandardPutFile dialog.
The parameters are the same as in StandardPutFile, plus:
Entry: alias = handle to alias to default directory, or nil if none.
----------------------------------------------------------------------------*/
void MyStandardPutFile (ConstStr255Param prompt, ConstStr255Param defaultName,
StandardFileReply *reply, AliasHandle alias)
{
Point where = {-1, -1};
PrepUserInteraction();
SetMenusTo(kAppleAllEnabled, 0, 0, 0, 0, 0);
gReply = reply;
gAlias = alias;
CustomPutFile(prompt, defaultName, reply, 0, where, gGetPutHookUPP,
gSFDialogFilterUPP, nil, nil, nil);
}
/*----------------------------------------------------------------------------
MyStandardAppendArticleHook
Dialog hook function for MyStandardAppendArticle.
----------------------------------------------------------------------------*/
static pascal short MyStandardAppendArticleHook (short item, DialogPtr dlg,
void *myDataPtr)
{
if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
if (item == kAppendEncodedCheckbox) {
*gSaveEncodedText = !(*gSaveEncodedText);
DlgSetCheck(dlg, item, *gSaveEncodedText);
return sfHookNullEvent;
} else if (item == sfHookFirstCall) {
DlgSetCheck(dlg, kAppendEncodedCheckbox, *gSaveEncodedText);
return SetStandardFileDirectoryFromAlias();
} else {
return item;
}
}
/*----------------------------------------------------------------------------
MyStandardAppendArticle
Present the append article dialog, with an extra checkbox to save
encoded text.
The parameters are the same as in StandardGetFile, plus:
Entry: *saveEncodedText = default value for save encoded text option.
alias = handle to alias to default directory, or nil if none.
Exit: *saveEncodedText = true to save encoded text.
----------------------------------------------------------------------------*/
void MyStandardAppendArticle (FileFilterYDUPP fileFilter, short numTypes,
char *typeListString, StandardFileReply *reply, Boolean *saveEncodedText,
AliasHandle alias)
{
Point where = {-1, -1};
SFTypeList typeList;
PrepUserInteraction();
SetMenusTo(kAppleAllEnabled, 0, 0, 0, 0, 0);
gReply = reply;
gSaveEncodedText = saveEncodedText;
gAlias = alias;
BlockMoveData(typeListString, typeList, 4*numTypes);
CustomGetFile(fileFilter, numTypes, typeList, reply, kAppendArtDlg, where,
gMyStandardAppendArticleHookUPP,
gSFDialogFilterUPP, nil, nil, nil);
}
/*----------------------------------------------------------------------------
MyStandardPutArticleHook
Dialog hook function for MyStandardPutArticle.
----------------------------------------------------------------------------*/
static pascal short MyStandardPutArticleHook (short item, DialogPtr dlg,
void *myDataPtr)
{
if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
if (item == kSaveEncodedCheckbox) {
*gSaveEncodedText = !(*gSaveEncodedText);
DlgSetCheck(dlg, item, *gSaveEncodedText);
return sfHookNullEvent;
} else if (item == kSaveThreadsToSeparateFilesCheckbox) {
*gSaveThreadsToSeparateFiles = !(*gSaveThreadsToSeparateFiles);
DlgSetCheck(dlg, item, *gSaveThreadsToSeparateFiles);
return sfHookNullEvent;
} else if (item == sfHookFirstCall) {
DlgSetCheck(dlg, kSaveEncodedCheckbox, *gSaveEncodedText);
DlgSetCheck(dlg, kSaveThreadsToSeparateFilesCheckbox,
*gSaveThreadsToSeparateFiles);
return SetStandardFileDirectoryFromAlias();
} else {
return item;
}
}
/*----------------------------------------------------------------------------
MyStandardPutArticle
Present the save article dialog, with an extra check box to save
encoded text.
The parameters are the same as in StandardPutFile, plus:
Entry: *saveEncodedText = default value for save encoded text option.
*saveThreadsToSeparateFiles = default value for save threads to
separate files options.
alias = handle to alias to default directory, or nil if none.
Exit: *saveEncodedText = true to save encoded text.
*saveThreadsToSeparateFiles = true to save threads to
separate files.
----------------------------------------------------------------------------*/
void MyStandardPutArticle (ConstStr255Param prompt, ConstStr255Param defaultName,
StandardFileReply *reply, Boolean *saveEncodedText,
Boolean *saveThreadsToSeparateFiles, AliasHandle alias)
{
Point where = {-1, -1};
PrepUserInteraction();
SetMenusTo(kAppleAllEnabled, 0, 0, 0, 0, 0);
gReply = reply;
gSaveEncodedText = saveEncodedText;
gSaveThreadsToSeparateFiles = saveThreadsToSeparateFiles;
gAlias = alias;
CustomPutFile(prompt, defaultName, reply, kSaveArtDlg, where,
gMyStandardPutArticleHookUPP,
gSFDialogFilterUPP, nil, nil, nil);
}
/*----------------------------------------------------------------------------
GetDirectoryFilter
Filter function for MyGetStandardDirectory.
----------------------------------------------------------------------------*/
static pascal Boolean GetDirectoryFilter (ParmBlkPtr pb, void *myDataPtr)
{
return (pb->fileParam.ioFlAttrib & 0x10) == 0 ||
(pb->fileParam.ioFlFndrInfo.fdFlags & fInvisible) != 0;
}
/*----------------------------------------------------------------------------
EnableBottomButton
Enable or disable the bottom directory selection button.
Entry: dlg = pointer to dialog.
enabled = true to enable button, false to disable it.
----------------------------------------------------------------------------*/
static void EnableBottomButton (DialogPtr dlg, Boolean enabled)
{
Handle itemHandle;
short itemType;
Rect box;
Boolean oldEnable;
GetDialogItem(dlg, kSelectDirButtonBottom, &itemType, &itemHandle, &box);
oldEnable = (itemType & itemDisable) == 0;
itemType = enabled ? itemType & (~itemDisable) : itemType | itemDisable;
SetDialogItem(dlg, kSelectDirButtonBottom, itemType, itemHandle, &box);
if ((itemType & ctrlItem) != 0 && oldEnable != enabled) {
HiliteControl((ControlHandle)itemHandle, enabled ? 0 : 255);
}
}
/*----------------------------------------------------------------------------
GetDirectoryHook
Dialog hook function for MyGetStandardDirectory.
----------------------------------------------------------------------------*/
static pascal short GetDirectoryHook (short item, DialogPtr dlg, void *myDataPtr)
{
Handle itemHandleTop, itemHandleBottom;
short itemType;
Rect boxTop, boxBottom;
CInfoPBRec pb;
short width;
CStr255 buttonTitle;
Str255 name;
short foundVRefNum;
long foundDirID;
Str255 select;
CStr255 fmt;
if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
GetPString(kStrFolderSelectNothing, select);
GetCString(kStrFolderSelectFmt, fmt);
if (GetWRefCon(dlg) != sfMainDialogRefCon) return item;
GetDialogItem(dlg, kSelectDirButtonTop, &itemType, &itemHandleTop, &boxTop);
GetDialogItem(dlg, kSelectDirButtonBottom, &itemType, &itemHandleBottom, &boxBottom);
if (item == sfHookFirstCall) {
pb.dirInfo.ioNamePtr = gDirBottom.name;
pb.dirInfo.ioVRefNum = -LMGetSFSaveDisk();
pb.dirInfo.ioFDirIndex = -1;
pb.dirInfo.ioDrDirID = LMGetCurDirStore();
PBGetCatInfo(&pb, false);
gDirBottom.vRefNum = pb.dirInfo.ioVRefNum;
gDirBottom.parID = pb.dirInfo.ioDrParID;
gDirTop = gDirBottom;
} else {
if (gReply->sfIsFolder || gReply->sfIsVolume || gReply->sfType == 'fdrp') {
gDirBottom = gReply->sfFile;
EnableBottomButton(dlg, true);
} else {
EnableBottomButton(dlg, false);
*gDirBottom.name = 0;
}
if (gReply->sfFile.parID == fsRtParID) {
FindFolder(kOnSystemDisk, kDesktopFolderType, kCreateFolder,
&foundVRefNum, &foundDirID);
pb.dirInfo.ioNamePtr = gDirTop.name;
pb.dirInfo.ioVRefNum = foundVRefNum;
pb.dirInfo.ioFDirIndex = -1;
pb.dirInfo.ioDrDirID = foundDirID;
PBGetCatInfo(&pb, false);
gDirTop.vRefNum = pb.dirInfo.ioVRefNum;
gDirTop.parID = pb.dirInfo.ioDrParID;
} else {
pb.dirInfo.ioNamePtr = gDirTop.name;
pb.dirInfo.ioVRefNum = gReply->sfFile.vRefNum;
pb.dirInfo.ioFDirIndex = -1;
pb.dirInfo.ioDrDirID = gReply->sfFile.parID;
PBGetCatInfo(&pb, false);
gDirTop.vRefNum = pb.dirInfo.ioVRefNum;
gDirTop.parID = pb.dirInfo.ioDrParID;
}
}
if (!EqualString(gPrevNameBottom, gDirBottom.name, false, true)) {
CopyPascalString(gPrevNameBottom, gDirBottom.name);
width = boxBottom.right - boxBottom.left - StringWidth(select) - 2*CharWidth(' ');
CopyPascalString(name, gDirBottom.name);
TruncString(width, name, smTruncMiddle);
p2cstr(name);
sprintf(buttonTitle, fmt, name);
c2pstr(buttonTitle);
SetControlTitle((ControlHandle)itemHandleBottom, (StringPtr)buttonTitle);
ValidRect(&boxBottom);
}
if (!EqualString(gPrevNameTop, gDirTop.name, false, true)) {
CopyPascalString(gPrevNameTop, gDirTop.name);
width = boxTop.right - boxTop.left - StringWidth(select) - 2*CharWidth(' ');
CopyPascalString(name, gDirTop.name);
TruncString(width, name, smTruncMiddle);
p2cstr(name);
sprintf(buttonTitle, fmt, name);
c2pstr(buttonTitle);
SetControlTitle((ControlHandle)itemHandleTop, (StringPtr)buttonTitle);
ValidRect(&boxTop);
}
/* Handle clicks on Select and Cancel buttons. */
if (item == kSelectDirButtonTop) {
gSelect = 1;
return sfItemCancelButton;
} else if (item == kSelectDirButtonBottom) {
gSelect = 2;
return sfItemCancelButton;
} else if (item == sfItemCancelButton) {
gSelect = 0;
return sfItemCancelButton;
}
return item;
}
/*----------------------------------------------------------------------------
MyStandardGetDirectory
Present a custom standard get file dialog to select a directory.
Exit: reply->sfGood = true if directory selected, false if dialog canceled.
reply->sfFile.vRefNum = vol ref num of selected directory.
reply->sfFile.parID = directory id of *parent* of selected directory.
reply->sfFile.name = name of selected directory.
*dirID = directory id of selected directory.
----------------------------------------------------------------------------*/
void MyStandardGetDirectory (StandardFileReply *reply, long *dirID)
{
Point point = {-1,-1};
SFTypeList typeList = {'ƒldr', 0, 0, 0};
CInfoPBRec pb;
Boolean targetIsFolder, wasAliased;
PrepUserInteraction();
SetMenusTo(kAppleAllEnabled, 0, 0, 0, 0, 0);
*gPrevNameTop = *gPrevNameBottom = 0;
gReply = reply;
CustomGetFile(gGetDirectoryFilterUPP, 1, typeList, reply, kDirSelectDlg, point,
gGetDirectoryHookUPP, gSFDialogFilterUPP, nil, nil, nil);
reply->sfGood = gSelect != 0;
if (!reply->sfGood) return;
if (gSelect == 1) {
reply->sfFile = gDirTop;
} else {
reply->sfFile = gDirBottom;
}
ResolveAliasFile(&reply->sfFile, true, &targetIsFolder, &wasAliased);
pb.dirInfo.ioNamePtr = reply->sfFile.name;
pb.dirInfo.ioVRefNum = reply->sfFile.vRefNum;
pb.dirInfo.ioFDirIndex = 0;
pb.dirInfo.ioDrDirID = reply->sfFile.parID;
PBGetCatInfo(&pb, false);
*dirID = pb.dirInfo.ioDrDirID;
}
/*----------------------------------------------------------------------------
sfutil_InitUPP
Initialize UPPs.
----------------------------------------------------------------------------*/
void sfutil_InitUPP (void)
{
gGetDirectoryFilterUPP = NewFileFilterYDProc(GetDirectoryFilter);
gGetDirectoryHookUPP = NewDlgHookYDProc(GetDirectoryHook);
gSFDialogFilterUPP = NewModalFilterYDProc(SFDialogFilter);
gGetPutHookUPP = NewDlgHookYDProc(GetPutHook);
gMyStandardPutArticleHookUPP = NewDlgHookYDProc(MyStandardPutArticleHook);
gMyStandardAppendArticleHookUPP = NewDlgHookYDProc(MyStandardAppendArticleHook);
}